home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
431_01
/
svr0.asm
< prev
next >
Wrap
Assembly Source File
|
1994-06-09
|
14KB
|
572 lines
;----------------------------------------------------------------------
;----------------------------------------------------------------------
;
; this is the server - specific assembly code.
; some notes:
; in thought i could interrupt DOS any time outside of a DOS
; critical area (flagged through int 2a/80 2a/81 2a/82) by simply
; swapping the SDA. surprise! i have used this technique many times
; in the past, but it seems that if both a background and foreground
; process are doing directory searches, they interfere with each
; other. that's what some of the more bizarre looking checks
; are all about.
;
;----------------------------------------------------------------------
;----------------------------------------------------------------------
SVR0_TEXT segment byte public 'CODE'
DGROUP group _DATA,_BSS
assume cs:SVR0_TEXT,ds:DGROUP
SVR0_TEXT ends
_DATA segment word public 'DATA'
d@ label byte
d@w label word
STK1LEN equ 512 ; stack while servicing any
stk1 db STK1LEN dup (0) ; interrupt
stk1end equ $
stk1sav dd 0
userintno db ? ; communications int #
_DATA ends
_BSS segment word public 'BSS'
b@ label byte
b@w label word
_BSS ends
extrn _ServerDispatch : far
extrn _UserInt : far
extrn _background : byte
extrn _SDA : far ptr
extrn _SDA_DOSBUSY : far ptr
extrn _lcl_SDA : far ptr
extrn _CDS_base : far ptr
extrn _lcl_CDS : far ptr
extrn _SDA_maxsize : word
extrn _SDA_minsize : word
extrn _CDS_TotalSize : word
extrn __Recieve : far
public _svr0_init
public _svr0_shutdown
public _svr0_GetSemaphores
public _svr0_SetDispatchFlag
public _svr0_ResetDispatchFlag
public _svr0_GetStackUsed
public _svr0_int1b
public _svr0_int23
public _svr0_int24
public _SwapDOS
SVR0_TEXT segment byte public 'CODE'
;
; these are easiest to keep in the code segment. bad
; practice though :)
;
semflag db 0 ; BIOS semaphore flags
doscrit db 0 ; DOS critical flag
callsvr db 0 ; call server pending
;
; swap two memory regious
; es:di --> src 1
; ds:si --> src 2
; cx = length
; exit:
; ax = ?
; cx = 0
; si/di are incremented [cx] bytes
; all others unchanged
; notes:
; i don't check that either di or si (or both) are at even addresses.
; this routine slows considerably if that is not the case!
;
swap proc near
pushf
cld ; want increment on string cmds
shr cx,1 ; cx /= 2 (holds # of words to move)
jz @@m1 ; if zero, skip
pushf ; save carry flag
@@ms:
mov bx,es:[di] ; swap 1 word at a time
movsw
mov [si-2],bx
loop @@ms
popf ; get carry back
@@m1:
jnc @@mr ; skip on no carry
mov ah,es:[di] ; otherwise move odd byte
movsb
mov [si-1],ah
@@mr:
popf
ret
swap endp
_SwapDOS proc far
push ax
push cx
push di
push si
push es
push ds ; swap SDA
mov cx,[_SDA_maxsize]
les di,[_SDA]
lds si,[_lcl_SDA]
call swap
pop ds
push ds ; swap CDS
mov cx,[_CDS_TotalSize]
les di,[_CDS_base]
lds si,[_lcl_CDS]
call swap
pop ds
pop es
pop si
pop di
pop cx
pop ax
ret
_SwapDOS endp
;----------------------------------------------------------------------
; test to see if the server needs to be called (or can be called)
; and do all of the necessary prep work.
;----------------------------------------------------------------------
svrhere db 0 ; local semaphore
_svr0_TestCallSvr proc far
pushf ; save things as i go along...
push ds
push bp
mov bp,DGROUP
mov ds,bp
cmp DGROUP:[_background],0 ; are we a background task?
jz @@__svr0a ; no, skip!
;
; everything from this test until we either
; set the flag or exit must not be interrupted!
;
cli
cmp cs:[svrhere],0 ; are we here?
jnz @@__svr0a ; yes, exit!
cmp cs:[semflag], 0 ; any BIOS locks?
jnz @@__svr0a ; yes, exit!
cmp cs:[doscrit],0 ; DOS in critical area?
jnz @@__svr0a ; yes, exit!
push di ; finally, check DOS busy
push es
les di,[_SDA_DOSBUSY]
cmp byte ptr es:[di],0 ; if DOS not busy, OK
jz @@_svr0_OK
cmp byte ptr es:[di],1 ; if DOS ct > 1, BAD
jnz @@_svr0_OK
cmp [int28here],1 ; if DOS ct IS 1
; and we're at int 28
; OK!
@@_svr0_OK:
pop es
pop di
jz @@__svr1 ; DOS not busy, continue
@@__svr0a:
jmp @@TestCallSvrR
@@__svr1:
mov cs:[svrhere],1 ; set semaphore
; save stack
mov word ptr DGROUP:[stk1sav],sp
mov word ptr DGROUP:[stk1sav+2],ss
cli ; set local stack
mov sp, offset stk1end
mov bp,ds
mov ss,bp
sti
push ax ; save remaining regs
push bx
push cx
push dx
push di
push si
push es
call __Recieve ; check for recieve
cmp cs:[callsvr],0 ; ready to call server?
jz @@__svr0_rcv ; no, done!
call _SwapDOS
call _ServerDispatch ; dispatch command
call _SwapDOS
@@__svr0_rcv:
pop es
pop si
pop di
pop dx
pop cx
pop bx
pop ax
cli
mov sp,word ptr DGROUP:[stk1sav]
mov ss,word ptr DGROUP:[stk1sav+2]
sti
mov cs:[svrhere],0 ; reset semaphore
@@TestCallSvrR:
pop bp
pop ds
popf
ret
_svr0_TestCallSvr endp
;----------------------------------------------------------------------
; my int 9 control-break handler (ignore)
;----------------------------------------------------------------------
_svr0_int1b proc far
iret
_svr0_int1b endp
;----------------------------------------------------------------------
; here is my control-break handler (ignore)
;----------------------------------------------------------------------
_svr0_int23 proc far
iret
_svr0_int23 endp
;----------------------------------------------------------------------
; my critical error handler (always return FAIL)
;----------------------------------------------------------------------
_svr0_int24 proc far
mov al,03h
iret
_svr0_int24 endp
;----------------------------------------------------------------------
; clock int
; we could only be here if the server was called during the last
; timer tick, but better safe than sorry.
;----------------------------------------------------------------------
int08here db 0
oldint08 dd 0
semint08 proc far
pushf ; emulate an INT 08
call cs:[oldint08]
cli
cmp cs:[int08here],0 ; check semaphore
jnz @@semint08R ; skip if here
inc cs:[int08here]
call _svr0_TestCallSvr ; try me
dec cs:[int08here]
@@semint08R:
iret ; finished
semint08 endp
;----------------------------------------------------------------------
; don't interrupt a disk action
;----------------------------------------------------------------------
oldint13 dd 0
semint13 proc far
inc cs:[semflag]
pushf
call cs:[oldint13]
pushf
dec cs:[semflag]
jnz @@__int13a
call _svr0_TestCallSvr
@@__int13a:
popf
retf 2 ; pop old flags
semint13 endp
;----------------------------------------------------------------------
; forward call calls to DOS, then try calling test server
; this assures that if a call to the server could not be put through
; due to DOS busy, it will be processed immediatly
;----------------------------------------------------------------------
oldint21 dd 0
semint21 proc far
call _svr0_TestCallSvr
jmp cs:[oldint21]
semint21 endp
;----------------------------------------------------------------------
; if in INT 0x28, we can interrupt DOS if 0 <= SDA_DOSBUSY <= 1
;----------------------------------------------------------------------
int28here db 0
oldint28 dd 0
semint28 proc far
inc cs:[int28here]
pushf
call cs:[oldint28]
call _svr0_TestCallSvr
dec cs:[int28here]
iret
semint28 endp
;----------------------------------------------------------------------
; dos set critical interrupt
;----------------------------------------------------------------------
oldint2a dd 0
semint2a proc far
pushf
cmp ah,80h ; entering DOS critical area?
jnz @@sem1 ; no, skip
inc cs:[doscrit] ; el